<template>
  <view class="image-viewer-container">
    <!-- 图片预览列表 - 只在非预览模式且有多张图片时显示 -->
    <view
      class="image-list"
      v-if="images.length > 1 && !previewMode && itemSize > 0"
    >
      <view
        class="image-item"
        v-for="(item, index) in images"
        :key="index"
        :style="{ width: itemSize + 'rpx', height: itemSize + 'rpx' }"
        @tap.stop="previewImage(index)"
      >
        <image
          class="thumbnail"
          :src="item.thumbnail || item.url"
          mode="aspectFill"
        />
        <view class="delete-btn" v-if="editable" @tap.stop="deleteImage(index)">
          <text class="iconfont icon-close"></text>
        </view>
      </view>

      <!-- 添加图片按钮 -->
      <view
        class="add-image"
        v-if="editable && images.length < maxCount"
        :style="{ width: itemSize + 'rpx', height: itemSize + 'rpx' }"
        @tap.stop="chooseImage"
      >
        <text class="iconfont icon-add"></text>
        <text class="add-text">添加图片</text>
      </view>
    </view>

    <!-- 全屏预览模式 -->
    <view
      class="preview-container"
      v-if="previewMode"
      :style="{
        'background-color': `rgba(0, 0, 0, ${opacity})`,
        transform: `translateY(${moveDistance}px)`,
      }"
    >
      <!-- 关闭按钮 -->
      <view class="close-btn" @tap.stop="closePreview">
        <text class="close-icon">×</text>
      </view>

      <!-- 图片预览区域 -->
      <view
        class="preview-image-container"
        @touchstart="touchStart"
        @touchmove="touchMove"
        @touchend="touchEnd"
        @tap.stop
      >
        <image
          class="preview-image"
          :src="currentImageUrl"
          :style="{ transform: `scale(${scale})` }"
          mode="aspectFit"
          @tap.stop
          @longtap="showActionMenu(currentImageUrl)"
        />
      </view>

      <!-- 添加背景蒙层，点击关闭 -->
      <view class="preview-mask" @tap="closePreview"></view>

      <!-- 底部控制栏 -->
      <view class="preview-controls">
        <!-- 图片索引 (仅在有多张图片时显示) -->
        <view class="current-index" v-if="images.length > 1">
          {{ currentIndex + 1 }}/{{ images.length }}
        </view>

        <!-- 操作按钮 -->
        <view class="control-buttons">
          <view class="control-btn" @tap.stop="zoomOut">
            <text class="btn-icon">-</text>
          </view>
          <view class="control-btn" @tap.stop="resetZoom">
            <text class="btn-icon">100%</text>
          </view>
          <view class="control-btn" @tap.stop="zoomIn">
            <text class="btn-icon">+</text>
          </view>
          <view class="control-btn" @tap.stop="saveImage(currentImageUrl)">
            <text class="btn-text">保存</text>
          </view>
        </view>
      </view>
    </view>
  </view>
</template>

<script>
export default {
  name: "ImageViewer",
  props: {
    // 图片列表数据 [{url: '图片地址', thumbnail: '缩略图地址(可选)'}]
    value: {
      type: Array,
      default: () => [],
    },
    // 是否可编辑（添加/删除图片）
    editable: {
      type: Boolean,
      default: false,
    },
    // 最大图片数量
    maxCount: {
      type: Number,
      default: 9,
    },
    // 列表中每个图片项的大小(rpx)
    itemSize: {
      type: Number,
      default: 200,
    },
    // 图片间距(rpx)
    gap: {
      type: Number,
      default: 10,
    },
    // 图片质量
    quality: {
      type: Number,
      default: 80,
    },
  },
  data() {
    return {
      images: [],
      previewMode: false,
      currentIndex: 0,
      touchStartY: 0,
      touchMoveY: 0,
      moveDistance: 0,
      opacity: 1,
      scale: 1, // 缩放比例
      minScale: 0.5, // 最小缩放
      maxScale: 3, // 最大缩放
      lastTouchDistance: 0, // 上次两指间距离
    };
  },
  computed: {
    // 当前显示图片的URL
    currentImageUrl() {
      if (this.images.length === 0) return "";
      return this.images[this.currentIndex]?.url || "";
    },
  },
  watch: {
    value: {
      handler(newVal) {
        this.images = JSON.parse(JSON.stringify(newVal || []));
      },
      immediate: true,
      deep: true,
    },
  },
  created() {
    // 若当前没有图片但传入了参数，检查预览模式
    if (this.images.length > 0 && this.itemSize === 0) {
      this.previewMode = true;
    }
  },
  methods: {
    // 选择图片
    chooseImage() {
      if (!this.editable) return;

      const self = this;
      uni.chooseImage({
        count: this.maxCount - this.images.length,
        sizeType: ["compressed"],
        sourceType: ["album", "camera"],
        success: (res) => {
          const tempFiles = res.tempFiles;

          // 处理选择的图片
          tempFiles.forEach((file) => {
            self.images.push({
              url: file.path,
              thumbnail: file.path,
              size: file.size,
            });
          });

          // 更新父组件的值
          this.$emit("input", this.images);
          this.$emit("change", this.images);
        },
      });
    },

    // 删除图片
    deleteImage(index) {
      if (!this.editable) return;

      this.images.splice(index, 1);
      // 更新父组件的值
      this.$emit("input", this.images);
      this.$emit("change", this.images);
    },

    // 预览图片
    previewImage(index) {
      this.currentIndex = index || 0;
      this.previewMode = true;
      this.moveDistance = 0;
      this.opacity = 1;
      this.scale = 1; // 重置缩放

      // 通知父组件已预览图片
      this.$emit("image-preview", {
        index: this.currentIndex,
        url: this.currentImageUrl,
      });
    },

    // 关闭预览
    closePreview() {
      this.previewMode = false;
      this.scale = 1; // 重置缩放

      // 通知父组件已关闭预览
      this.$emit("preview-close");
    },

    // 切换预览的图片 (用于多图模式)
    switchImage(direction) {
      if (this.images.length <= 1) return;

      // 如果正在缩放，先重置缩放
      if (this.scale !== 1) {
        this.scale = 1;
        return;
      }

      if (direction === "next") {
        this.currentIndex = (this.currentIndex + 1) % this.images.length;
      } else {
        this.currentIndex =
          (this.currentIndex - 1 + this.images.length) % this.images.length;
      }

      // 通知父组件已切换图片
      this.$emit("image-change", {
        index: this.currentIndex,
        url: this.currentImageUrl,
      });
    },

    // 放大图片
    zoomIn() {
      this.scale = Math.min(this.maxScale, this.scale + 0.5);
    },

    // 缩小图片
    zoomOut() {
      this.scale = Math.max(this.minScale, this.scale - 0.5);
    },

    // 重置缩放
    resetZoom() {
      this.scale = 1;
    },

    // 显示操作菜单
    showActionMenu(url) {
      if (!url) return;

      uni.showActionSheet({
        itemList: ["保存图片"],
        success: (res) => {
          if (res.tapIndex === 0) {
            this.saveImage(url);
          }
        },
      });
    },

    // 保存图片到相册
    saveImage(url) {
      if (!url) {
        uni.showToast({
          title: "图片地址无效",
          icon: "none",
        });
        return;
      }

      uni.saveImageToPhotosAlbum({
        filePath: url,
        success: () => {
          uni.showToast({
            title: "图片已保存到相册",
            icon: "success",
          });
        },
        fail: (err) => {
          console.error("保存图片失败", err);
          if (err.errMsg.includes("auth deny")) {
            uni.showModal({
              title: "提示",
              content: "需要授权保存图片到相册",
              success: (res) => {
                if (res.confirm) {
                  uni.openSetting();
                }
              },
            });
          } else {
            uni.showToast({
              title: "保存失败",
              icon: "none",
            });
          }
        },
      });
    },

    // 触摸开始
    touchStart(e) {
      if (e.touches.length === 1) {
        // 单指触摸 - 记录开始位置用于下滑关闭
        this.touchStartY = e.touches[0].clientY;
      } else if (e.touches.length === 2) {
        // 双指触摸 - 记录初始距离用于缩放
        const dx = e.touches[0].clientX - e.touches[1].clientX;
        const dy = e.touches[0].clientY - e.touches[1].clientY;
        this.lastTouchDistance = Math.sqrt(dx * dx + dy * dy);
      }
    },

    // 触摸移动
    touchMove(e) {
      if (e.touches.length === 1) {
        // 单指移动 - 处理下滑关闭
        this.touchMoveY = e.touches[0].clientY;

        // 只有在缩放级别为1时才允许下滑关闭
        if (this.scale === 1) {
          this.moveDistance = Math.max(0, this.touchMoveY - this.touchStartY);

          // 计算背景透明度 (0.3-1)，移动超过300px时透明度为0.3
          const maxDistance = 300;
          this.opacity = Math.max(
            0.3,
            1 - (this.moveDistance / maxDistance) * 0.7
          );
        }
      } else if (e.touches.length === 2) {
        // 双指移动 - 处理缩放
        const dx = e.touches[0].clientX - e.touches[1].clientX;
        const dy = e.touches[0].clientY - e.touches[1].clientY;
        const distance = Math.sqrt(dx * dx + dy * dy);

        // 计算缩放比例变化
        if (this.lastTouchDistance > 0) {
          const scale = this.scale * (distance / this.lastTouchDistance);
          this.scale = Math.min(this.maxScale, Math.max(this.minScale, scale));
        }

        this.lastTouchDistance = distance;
      }
    },

    // 触摸结束
    touchEnd(e) {
      // 处理下滑关闭
      if (this.moveDistance > 150 && this.scale === 1) {
        this.closePreview();
      } else {
        // 否则回弹
        this.moveDistance = 0;
        this.opacity = 1;
      }

      // 重置双指距离
      this.lastTouchDistance = 0;
    },
  },
};
</script>

<style lang="scss" scoped>
.image-viewer-container {
  width: 100%;

  .image-list {
    display: flex;
    flex-wrap: wrap;

    .image-item {
      position: relative;
      margin-right: v-bind(gap + "rpx");
      margin-bottom: v-bind(gap + "rpx");
      overflow: hidden;
      border-radius: 8rpx;

      .thumbnail {
        width: 100%;
        height: 100%;
      }

      .delete-btn {
        position: absolute;
        top: 0;
        right: 0;
        width: 40rpx;
        height: 40rpx;
        background-color: rgba(0, 0, 0, 0.5);
        display: flex;
        justify-content: center;
        align-items: center;
        color: #fff;
        font-size: 24rpx;
      }
    }

    .add-image {
      display: flex;
      flex-direction: column;
      justify-content: center;
      align-items: center;
      background-color: #f7f7f7;
      border: 1px dashed #ddd;
      border-radius: 8rpx;
      margin-right: v-bind(gap + "rpx");
      margin-bottom: v-bind(gap + "rpx");

      .iconfont {
        font-size: 48rpx;
        color: #999;
        margin-bottom: 10rpx;
      }

      .add-text {
        font-size: 24rpx;
        color: #999;
      }
    }
  }

  .preview-container {
    position: fixed;
    top: 0;
    left: 0;
    width: 100vw;
    height: 100vh;
    background-color: #000;
    z-index: 9999;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;

    /* 背景蒙层 */
    .preview-mask {
      position: absolute;
      top: 0;
      left: 0;
      width: 100%;
      height: 100%;
      z-index: 9998;
    }

    /* 关闭按钮样式 */
    .close-btn {
      position: absolute;
      top: 40rpx;
      right: 40rpx;
      width: 80rpx;
      height: 80rpx;
      border-radius: 50%;
      background-color: rgba(0, 0, 0, 0.5);
      display: flex;
      justify-content: center;
      align-items: center;
      z-index: 10001;

      .close-icon {
        color: #fff;
        font-size: 60rpx;
        font-weight: 200;
        line-height: 1;
      }
    }

    /* 图片预览容器 */
    .preview-image-container {
      width: 100%;
      height: 100%;
      display: flex;
      align-items: center;
      justify-content: center;
      overflow: hidden;
      z-index: 9999;

      .preview-image {
        width: 100%;
        height: 100%;
        transition: transform 0.2s ease;
      }
    }

    /* 底部控制栏 */
    .preview-controls {
      position: absolute;
      bottom: 100rpx;
      left: 0;
      width: 100%;
      display: flex;
      flex-direction: column;
      align-items: center;
      padding: 0 30rpx;
      box-sizing: border-box;
      z-index: 10001;

      .current-index {
        color: #fff;
        font-size: 28rpx;
        margin-bottom: 30rpx;
        background-color: rgba(0, 0, 0, 0.5);
        padding: 8rpx 20rpx;
        border-radius: 30rpx;
      }

      .control-buttons {
        display: flex;
        align-items: center;
        justify-content: center;
        background-color: rgba(0, 0, 0, 0.5);
        border-radius: 44rpx;
        padding: 10rpx;
      }

      .control-btn {
        width: 80rpx;
        height: 80rpx;
        border-radius: 40rpx;
        display: flex;
        align-items: center;
        justify-content: center;
        margin: 0 10rpx;
        background-color: rgba(255, 255, 255, 0.1);

        .btn-icon {
          color: #fff;
          font-size: 36rpx;
          font-weight: bold;
        }

        .btn-text {
          color: #fff;
          font-size: 26rpx;
        }
      }
    }
  }
}
</style>
